<?php
/**
 * Created by PhpStorm.
 * User: Jan-Home
 * Date: 2018/4/5 0005
 * Time: 15:22
 */

namespace Gitee\Helper;

use Ke\App;
use Ke\Uri;
use voku\helper\AntiXSS;

class CurlRequest
{
	
	const GET = 'get';
	
	const POST = 'post';
	
	/** @var Uri */
	protected $uri = null;
	
	protected $method = self::GET;
	
	protected $postData = [];
	
	protected $userAgent = '';
	
	// curl 根域名证书验证
	protected $cacert = '';
	
	protected $sslVerifyPeer = 0;
	
	protected $sslVerifyHost = 0;
	
	protected $headers = [];
	
	private $error = '';
	
	private $errorno = 0;
	
	private $isSend = false;
	
	private $curl = null;
	
	private $response = '';
	
	private $isSSlVerifyHost = 0;
	
	public static function new($uri = null)
	{
		return new static($uri);
	}
	
	public function __construct($uri = null)
	{
		if (isset($uri))
			$this->setUri($uri);
	}
	
	public function setUri($uri)
	{
		if (!($uri instanceof Uri))
			$uri = new Uri($uri);
		$this->uri = $uri;
		return $this;
	}
	
	public function getUri(): Uri
	{
		return $this->uri;
	}
	
	public function getStringUri(): string
	{
		return $this->uri->toUri(true);
	}
	
	public function setMethod(string $method)
	{
		$method = strtolower($method);
		if ($method === self::GET || $method === self::POST)
			$this->method = $method;
		return $this;
	}
	
	public function getMethod(): string
	{
		return strtolower($this->method);
	}
	
	public function isPost(): bool
	{
		return $this->getMethod() === self::POST;
	}
	
	public function setUserAgent(string $userAgent = null)
	{
		if (empty($userAgent))
			$userAgent = '';
		$this->userAgent = $userAgent;
		return $this;
	}
	
	public function getUserAgent(): string
	{
		return $this->userAgent;
	}
	
	
	public function setHeaders(array $headers)
	{
		foreach ($headers as $key => $header) {
			$this->headers[$key] = $header;
		}
		return $this;
	}
	
	public function makeOptions()
	{
		//@todo 暂时这样处理URI
		// $uri = $this->uri->toUri(true);
		// $uriData = explode('?', $uri);
		// if(!empty($uriData) && isset($uriData[0]) && isset($uriData[1])) {
		// 	$url = substr($uriData[0], 0, strlen($uriData[0]) - 1);
		// 	$newUrl = $url . '?' . $uriData[1];
		// } else {
		$newUrl = $this->uri->toUri(true);
		// }
		
		$options = [
			CURLOPT_RETURNTRANSFER => 1,
			CURLOPT_URL            => $newUrl,
			CURLOPT_SSL_VERIFYPEER => false, // 信任任何证书
			CURLOPT_SSL_VERIFYHOST => $this->isSSlVerifyHost, // 检查证书中是否设置域名
			// CURLOPT_FOLLOWLOCATION => true,
		];
		
		if (!empty($this->userAgent))
			$options[CURLOPT_USERAGENT] = $this->userAgent;
		
		$headers = [];
		if (!empty($this->headers))
			$headers = $this->headers;
		
		if (strtolower($this->method) === 'post') {
			$options[CURLOPT_POST] = 1;
			$bodyLength = 0;
			if (!empty($this->postData)) {
				$bodyString = http_build_query($this->postData);
				$bodyLength = mb_strlen($bodyString);
				$options[CURLOPT_POSTFIELDS] = $bodyString;
			}
//			$headers[] = 'Content-Type: application/x-www-form-urlencoded;';
//			$headers[] = 'Charset=UTF-8;';
//			$headers[] = 'Content-Length: ' . $bodyLength;
		}
		
		if (!empty($headers))
			$options[CURLOPT_HTTPHEADER] = $headers;
		return $options;
	}
	
	public function send(array $data = null)
	{
		if (isset($data)) {
			$antiXSS = new AntiXSS();
			$data = $antiXSS->xss_clean($data);
			if ($this->isPost())
				$this->postData = $data + $this->postData;
			else
				$this->uri->mergeQuery($data);
		}
		
		$options = $this->makeOptions();
		
		$this->curl = curl_init();
		curl_setopt_array($this->curl, $options);
		$this->response = curl_exec($this->curl);
		
		$this->isSend = true;
		$this->error = curl_error($this->curl);
		$this->errorno = curl_errno($this->curl);
		curl_close($this->curl);
		return $this;
	}
	
	public function get(array $data = null)
	{
		$this->method = self::GET;
		return $this->send($data);
	}
	
	public function post(array $data = null)
	{
		$this->method = self::POST;
		return $this->send($data);
	}
	
	
	public function getError()
	{
		if (!$this->isSend) {
			return 0;
		}
		if ($this->errorno > 0)
			return $this->errorno;
		return 0;
	}
	
	
	public function getResponse()
	{
		return $this->response;
	}
	
	public function setSSLVerifyHost(int $val)
	{
		return $this->isSSlVerifyHost = $val;
	}
}